#!/bin/sh
#(c) Copyright Barry Kauler Dec. 2010. License GPL v3 /usr/share/doc/legal.
#called from pupdial. Based upon earlier scripts by Richard Erwin.
#there were scripts in /etc/init.d created by Richard, now moved to here.
#101205 use modem-stats to eliminate non-responsive ttyUSB ports.
#101206 wait. remember previous modem.
#101207 if usb-modeswitch has already set /dev/gsmmodem, use it.
#101207 modem plugged in at bootup, may not trigger usb-modeswitch, replay uevents.
#101210, 101211 tweaks.
#110302 wasn't getting the right uevents for my 3g modem, use 'udevadm trigger'.
#120202 internationalized.
#120908 rerwin: Removed Dgcmodem logic, already handled by Cdcacm section; moved Hso section to eliminate need for flag to maintain priority (used in init scripts to override execution sequence by script name).  Code moved, shifted or deleted, but not otherwise changed, except for "probe order" variables.

export TEXTDOMAIN=pupdial_init_hotpluggable
export OUTPUT_CHARSET=UTF-8

#hso.ko: this site http://www.pharscape.org/hso.html states that the hso driver is in kernel
#2.6.27. Yes, it is in kernel/drivers/net/usb/hso.ko. It is also in the 2.6.30.* kernel.
#however it is missing from 2.6.31 and later kernels...
#oh, i see why. I have configured 2.6.31 and later with 'rfkill' turned off, which
#hso requires: in kernel source drivers/net/usb/Kconfig:
#config USB_HSO
#	tristate "Option USB High Speed Mobile Devices"
#	depends on USB && RFKILL
#101210 ...I was able to compile it separately, have put it in zzz pkg, for testing.
#110302 2.6.32.28 kernel has rfkill and hso enabled. no longer using zzz pkg.

#101206
prevMODEM=''
if [ -h /dev/modem ];then #maybe set by internal modem detected at bootup, or previous run of pupdial this session.
 prevMODEM="`readlink /dev/modem | sed -e 's%/dev/%%'`"
 rm -f /dev/modem
fi

chat_with_func() { #device passed in, ex: ttyUSB0
 rm -f /tmp/pupdial_port_test 2> /dev/null
 #TODO maybe send +++ to return modem to command-mode.
 #hangs if modem unplugged or turned off (contrary to what docs say)...
 modem-stats -c "ATZ" $1 > /tmp/pupdial_port_test &
 sleep 5 #v413
 killall modem-stats
 if [ -e /tmp/pupdial_port_test ];then
  if [ -s /tmp/pupdial_port_test ];then #nonzero size.
   grep "^OK" /tmp/pupdial_port_test > /dev/null 2>&1
   [ $? -eq 0 ] && return 0 #success
  fi
 fi
 return 1
}

MODEM=''

hPID=0 #101211 do not display msg on 2nd entry...
if [ ! $1 ];then
 /usr/lib/gtkdialog/box_splash -placement center -close never -fontsize large -text "$(gettext 'Please wait, probing for hotpluggable (external) modems...')" &
 hPID=$!
fi

#101206 wait...
BRKCNT=0
while [ $BRKCNT -lt 40 ];do #101211 bump 30 to 40.
 OK=0
 [ "`ls -1 /pinstall.*.sh 2>/dev/null`" = "" ] && [ "`pidof usb_modeswitch`" = "" ] && [ "`pidof usb_modeswitch_status`" = "" ] && OK=$(($OK+1))
 sleep 1
 [ "`ls -1 /pinstall.*.sh 2>/dev/null`" = "" ] && [ "`pidof usb_modeswitch`" = "" ] && [ "`pidof usb_modeswitch_status`" = "" ] && OK=$(($OK+1))
 [ -f /tmp/usb_modeswitch_status_flag_success ] && OK=2 #see usb_modeswitch_status.
 [ $OK -eq 2 ] && break
 BRKCNT=$(($BRKCNT+1))
done

#101207 if usb-modeswitch has already set this, use it...
if [ -h /dev/gsmmodem ];then
 gMODEM="`readlink /dev/gsmmodem`"
 if [ -e /dev/${gMODEM} ];then
  ln -snf $gMODEM /dev/modem
  [ $hPID -ne 0 ] && kill $hPID
  exit
 else
  rm -f /dev/gsmmodem
 fi
fi

#101206 has anything changed?...
prevUSBIDS=''
USBIDS="`lsusb 2>/dev/null | tr -s ' ' | cut -f 6 -d ' ' | sort -u | tr '\n' ' '`"
[ -f /var/local/pupdial/usbids ] && prevUSBIDS="`cat /var/local/pupdial/usbids`"
echo -n "$USBIDS" > /var/local/pupdial/usbids

#hso.ko not always present... well check them all...
USBSERIAL='' ; CDC_ACM='' ; HSO='' ; NOZOMI='' ; IPWIRELESS='' #120908
if modinfo usbserial >/dev/null 2>&1 ;then USBSERIAL=usbserial ;fi
if modinfo cdc_acm >/dev/null 2>&1 ;then CDC_ACM=cdc_cm ;fi
if modinfo hso >/dev/null 2>&1 ;then HSO=hso ;fi
if modinfo nozomi >/dev/null 2>&1 ;then NOZOMI=nozomi ;fi
if modinfo ipwireless >/dev/null 2>&1 ;then IPWIRELESS=ipwireless ;fi

USBMODEMS="$HSO $USBSERIAL $CDC_ACM" #120908...
PCMCIAMODEMS="$IPWIRELESS $NOZOMI"
#listed in order that we should probe... $HSO $USBSERIAL $CDC_ACM $IPWIRELESS $NOZOMI

#####Hso#####
if [ "$HSO" ];then
 MODEM=''
 [ -h /dev/modem ] && MODEM="`readlink /dev/modem | grep -v '^ttyHS[0-9]$'`"
 if [ "$MODEM" = "" ];then #If a different modem selected, quit.
  if lsmod | grep '^hso ' >/dev/null ;then
   WAITCNT=0 ; WAITMAX=10
   until [ "$MODEM" != "" ];do
    MODEM="`grep -l -s 'Modem' /sys/class/tty/ttyHS[0-9][0-9]*/hsotype | head -n 1 | cut -f 5 -d /`"
    if [ "$MODEM" = "" ];then
     WAITCNT=`expr $WAITCNT + 1`
     [ $WAITCNT -gt $WAITMAX ] && break
     sleep 1
    fi
   done
   if [ $WAITCNT -le $WAITMAX ];then
    #Even if /dev/modem already set, ensure it matches detected modem.
    [ -h /dev/modem ] && rm /dev/modem
    ln -snf $MODEM /dev/modem
    [ -h /dev/ttyS_HS ] && rm /dev/ttyS_HS
    ln -snf $MODEM /dev/ttyS_HS #for pupdial probe
   fi
  fi
 fi
fi

#####Allusbserial#####
if [ "$USBSERIAL" ];then
 if [ ! -h /dev/modem ];then #If a different modem selected, quit.
  if lsmod | grep '^usbserial ' >/dev/null ;then
   #Select interrupt-type device - first one or one identified in log as modem.
   INTERRUPTLIST="`grep -H -s 'Interrupt' /sys/bus/usb/devices/*-*:*.*/ep_??/type | cut -f 1-6 -d /`"
   DEVLISTUSB="`ls -1 -d /sys/bus/usb/devices/*-*:*.*/tty????* 2>/dev/null | sed 's/ /\n/g' | grep -F "$INTERRUPTLIST" | cut -f 7 -d / | sed 's/\(tty...\)\([0-9]$\)/\10\2/' | sort | sed 's/\(tty...\)\(0\)/\1/'`"
   DEVMLIST="`grep -s 'converter now attached' /var/log/messages | grep ' modem ' | grep -o 'ttyUSB[0-9][0-9]*' | sort -u`"
   if [ "$DEVLISTUSB" != "" ] && [ "$DEVMLIST" != "" ];then
    MODEMS="`echo "$DEVLISTUSB" | grep -F "$DEVMLIST"`"
   else
    MODEMS="$DEVMLIST"
   fi
   if [ "$MODEMS" != "" ];then #101205
    #101206 avoid unecessary modem probing...
    prevUSBMODEM=''
    [ -f /var/local/pupdial/usb_modem_port ] && prevUSBMODEM="`cat /var/local/pupdial/usb_modem_port`"
    [ "$USBIDS" = "$prevUSBIDS" ] && [ "$prevUSBMODEM" ] && [ "`echo "$MODEMS" | grep "$prevUSBMODEM"`" != "" ] && ln -snf $prevUSBMODEM /dev/modem
    if [ ! -h /dev/modem ];then
     for MODEM in $MODEMS
     do
      chat_with_func /dev/${MODEM}
      [ $? -eq 0 ] && break
      MODEM=''
     done
     if [ "$MODEM" != "" ];then
      ln -snf $MODEM /dev/modem
      echo -n "$MODEM" > /var/local/pupdial/usb_modem_port
     fi
    fi
   fi
  fi
 fi
fi

#####Cdcacm/Dgcmodem#####
if [ "$CDC_ACM" ];then
 if [ ! -h /dev/modem ];then #If a different modem selected, quit.
  if lsmod | grep '^cdc_acm ' >/dev/null ;then
   #Select interrupt-type device - first one or one identified in log as modem.
   INTERRUPTLIST="`grep -H -s 'Interrupt' /sys/bus/usb/devices/*-*:*.*/ep_??/type | cut -f 1-6 -d /`"
   DEVLISTACM="`ls -1 -d /sys/bus/usb/devices/*-*:*.*/tty/tty????* 2>/dev/null | sed 's/ /\n/g' | grep -F "$INTERRUPTLIST" | cut -f 8 -d / | sed 's/\(tty...\)\([0-9]$\)/\10\2/' | sort | sed 's/\(tty...\)\(0\)/\1/'`"
   DEVMLIST="`grep -s ': USB ACM device$' /var/log/messages | grep -o 'ttyACM[0-9][0-9]*' | sort -u`"
   if [ "$DEVLISTACM" != "" ] && [ "$DEVMLIST" != "" ];then
    MODEM="`echo "$DEVLISTACM" | grep -F "$DEVMLIST" | head -n 1`"
   else
    MODEM="`echo "$DEVMLIST" | head -n 1`"
   fi
   if [ "$MODEM" != "" ];then
    [ ! -e /dev/$MODEM ] && [ -e /dev/input/$MODEM ] && ln -snf input/$MODEM /dev/$MODEM  #device name for pupdial
    ln -snf $MODEM /dev/modem
   fi
  fi
 fi
fi #120908 end

#####Ipwireless#####
if [ "$IPWIRELESS" ];then
 if [ ! -h /dev/modem ];then #If a different modem selected, quit.
  if lsmod | grep '^ipwireless ' >/dev/null ;then
   ln -snf ttyIPWp0 ttyS_ttyIPWp0
   ln -snf ttyS_IPWp0 /dev/modem
  fi
 fi
fi

#####Nozomi#####
if [ "$NOZOMI" ];then
 if [ ! -h /dev/modem ];then #If a different modem selected, quit.
  if lsmod | grep '^nozomi ' >/dev/null ;then
   ln -snf noz0 /dev/modem
   ln -snf noz0 /dev/ttyS_NOZ0 #for pupdial probe
  fi
 fi
fi

#110302 have modified /etc/rc.d/rc.sysinit so this section probably not needed...
#101207 modem plugged in at bootup, may not trigger usb-modeswitch, replay uevents...
if [ ! $1 ];then #101211 gets reentered, see below.
 if [ ! -h /dev/modem ];then
  [ -e /sys/bus/pcmcia/devices ] && NEWPCMCIA="`ls /sys/bus/pcmcia/devices/*/uevent 2>/dev/null | tr '\n' ' '`"
  #110302 usb done differently below...
  for ONEUEVENT in ${NEWPCMCIA}${NEWUSB}
  do
   ONEPATH="`dirname $ONEUEVENT`"
   #the check for 'modalias' file is maybe needed for old kernel?...
   [ ! -e ${ONEPATH}/modalias ] && [ "`grep 'MODALIAS' $ONEUEVENT`" = "" ] && continue
   echo add > $ONEUEVENT
   sleep 0.1
  done
  #110302 wasn't getting the right uevents for my 3g modem...
  udevadm trigger --action=add --subsystem-match=usb
  sleep 2 #4 #101211 give plenty of time for usb-modeswitch to start.
  kill $hPID #101211
  /usr/sbin/pupdial_init_hotpluggable 2
 else
  kill $hPID
 fi
fi
###END###
